﻿using WebApp.BLL;
using WebApp.Common;
using WebApp.Models;
using WebApp.ViewModels;
using WebApp.Web.Core;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace kzjd.rycp.WebApp
{
    public static class MVCHelpers
    {

        #region Span

        public static MvcHtmlString Span(this HtmlHelper htmlHelper, string name, string text, object htmlAttributes)
        {
            return Span(htmlHelper, name, text, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString Span(this HtmlHelper htmlHelper, string name, string text, IDictionary<string, object> htmlAttributes)
        {
            var sb = new StringBuilder();

            var span = new TagBuilder("span");
            span.MergeAttribute("id", name);
            span.MergeAttributes(htmlAttributes);
            span.InnerHtml = text;

            sb.Append(span.ToString());

            return MvcHtmlString.Create(sb.ToString());
        }

        #endregion

        #region DropDownList

        public static MvcHtmlString DropDownList(this HtmlHelper htmlHelper, string name, string selectedValue, IEnumerable<SelectListItem> selectList, object htmlAttributes)
        {
            return DropDownList(htmlHelper, name, selectedValue, selectList, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString DropDownList(this HtmlHelper htmlHelper, string name, string selectedValue, IEnumerable<SelectListItem> selectList, string optionLabel, object htmlAttributes)
        {
            var optionslist = selectList.Select(p => new SelectListItem
            {
                Value = p.Value,
                Text = p.Text,
                Selected = (p.Value == selectedValue)
            }).ToList();
            optionslist.Insert(0, new SelectListItem
            {
                Value = "",
                Text = optionLabel
            });

            return DropDownList(htmlHelper, name, selectedValue, optionslist, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString DropDownList(this HtmlHelper htmlHelper, string name, string selectedValue, IEnumerable<SelectListItem> selectList, IDictionary<string, object> htmlAttributes)
        {
            var optionslist = selectList.Select(p => new SelectListItem
            {
                Value = p.Value,
                Text = p.Text,
                Selected = (p.Value == selectedValue)
            });

            var sb = new StringBuilder();

            var input = new TagBuilder("select");
            input.MergeAttribute("id", name);
            input.MergeAttribute("name", name);
            input.MergeAttributes(htmlAttributes);
            sb.Append(input.ToString(TagRenderMode.StartTag));

            foreach (var item in optionslist)
            {
                var option = new TagBuilder("option");
                option.InnerHtml = item.Text;
                option.MergeAttribute("value", Utils.NvStr(item.Value));
                if (item.Selected)
                {
                    option.MergeAttribute("selected", "selected");
                }
                sb.Append(option.ToString());
            }

            sb.Append(input.ToString(TagRenderMode.EndTag));

            return MvcHtmlString.Create(sb.ToString());
        }

        #endregion

        #region RadioListUL

        public static MvcHtmlString RadioListUL(this HtmlHelper htmlHelper, string name, string selectedValue, string[] valueList, object htmlAttributes, string classname = "radio")
        {
            var list = valueList.Select(p => new SelectListItem
            {
                Value = p,
                Text = p,
                Selected = (p == selectedValue)
            });

            return RadioListUL(htmlHelper, name, list, htmlAttributes, classname);
        }

        public static MvcHtmlString RadioListUL(this HtmlHelper htmlHelper, string name, string selectedValue, IEnumerable<SelectListItem> selectList, object htmlAttributes, string classname = "radio")
        {
            var list = selectList.Select(p => new SelectListItem
            {
                Value = p.Value,
                Text = p.Text,
                Selected = p.Value == selectedValue
            });

            return RadioListUL(htmlHelper, name, list, htmlAttributes, classname);
        }

        public static MvcHtmlString RadioListUL(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, object htmlAttributes, string classname = "radio")
        {
            return RadioListUL(htmlHelper, name, selectList, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), classname);
        }

        public static MvcHtmlString RadioListUL(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, IDictionary<string, object> htmlAttributes, string classname = "radio")
        {
            return MvcHtmlString.Create(GetRadioUIHtmlBuilder(htmlHelper, name, selectList, htmlAttributes, classname).ToString());
        }

        private static StringBuilder GetRadioUIHtmlBuilder(HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, IDictionary<string, object> htmlAttributes, string classname)
        {
            if (string.IsNullOrEmpty(classname)) classname = "radio";

            var ul = new TagBuilder("ul");
            ul.MergeAttribute("class", classname);
            ul.MergeAttribute("id", name);

            var sb = new StringBuilder();
            sb.Append(ul.ToString(TagRenderMode.StartTag));

            string selectedValue = "";
            var optionId = 0;
            foreach (var item in selectList)
            {
                var ischecked = false;
                if (item.Selected)
                {
                    selectedValue = item.Value;
                    ischecked = true;
                }

                var li = new TagBuilder("li");
                if (ischecked) li.MergeAttribute("class", "checked");

                var radio = new TagBuilder("input");
                radio.MergeAttribute("id", name + "_" + optionId);
                radio.MergeAttribute("name", name);
                radio.MergeAttribute("type", "radio");
                radio.MergeAttribute("value", item.Value);
                //radio.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
                if (ischecked) radio.MergeAttribute("checked", "checked");
                if (htmlAttributes != null)
                {
                    if (true.Equals(htmlAttributes["disabled"])
                        || "true".Equals(htmlAttributes["disabled"])
                        || "disabled".Equals(htmlAttributes["disabled"]))
                    {
                        radio.MergeAttribute("disabled", "disabled");
                    }
                }

                var label = new TagBuilder("label");
                label.MergeAttribute("for", name + "_" + optionId);
                label.SetInnerText(item.Text);

                sb.Append(li.ToString(TagRenderMode.StartTag));
                sb.Append(radio.ToString());
                sb.Append(label.ToString());
                sb.Append(li.ToString(TagRenderMode.EndTag));

                optionId++;
            }

            var hidden = new TagBuilder("input");
            hidden.MergeAttribute("id", name + "_val");
            hidden.MergeAttribute("name", name + "_val");
            hidden.MergeAttribute("type", "hidden");
            hidden.MergeAttribute("value", selectedValue);
            hidden.MergeAttributes(htmlAttributes, true);
            sb.Append(hidden.ToString());

            sb.Append(ul.ToString(TagRenderMode.EndTag));

            return sb;
        }

        #endregion

        #region CheckBoxListUL

        public static MvcHtmlString CheckBoxListUL(this HtmlHelper htmlHelper, string name, string selectedValue, string[] values, object htmlAttributes, string classname = "checkbox")
        {
            SelectList selectList = new SelectList(values);

            return CheckBoxListUL(htmlHelper, name, selectedValue, selectList, htmlAttributes, classname);
        }

        public static MvcHtmlString CheckBoxListUL(this HtmlHelper htmlHelper, string name, string selectedValue, IEnumerable<SelectListItem> selectList, object htmlAttributes, string classname = "checkbox")
        {
            var selectListItems = selectList as SelectListItem[] ?? selectList.ToArray();
            if (selectListItems.Any())
            {
                foreach (var item in selectListItems)
                {
                    if (item.Value == selectedValue)
                        item.Selected = true;
                }
            }

            return CheckBoxListUL(htmlHelper, name, selectList, htmlAttributes, classname);
        }

        public static MvcHtmlString CheckBoxListUL(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, object htmlAttributes, string classname = "checkbox")
        {
            return MvcHtmlString.Create(GetCheckBoxULHtmlBuilder(htmlHelper, name, selectList, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), classname).ToString());
        }

        private static StringBuilder GetCheckBoxULHtmlBuilder(HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, IDictionary<string, object> htmlAttributes, string classname)
        {
            if (string.IsNullOrEmpty(classname)) classname = "checkbox";

            var ul = new TagBuilder("ul");
            ul.MergeAttribute("class", classname);
            ul.MergeAttribute("id", name);

            var sb = new StringBuilder();
            sb.Append(ul.ToString(TagRenderMode.StartTag));

            string selectedValue = "";
            var optionId = 0;
            var selectListItems = selectList as SelectListItem[] ?? selectList.ToArray();
            if (selectListItems.Any())
            {
                foreach (var item in selectListItems)
                {
                    var ischecked = false;
                    if (item.Selected)
                    {
                        selectedValue = item.Value;
                        ischecked = true;
                    }

                    var li = new TagBuilder("li");
                    if (ischecked) li.MergeAttribute("class", "checked");

                    var radio = new TagBuilder("input");
                    radio.MergeAttribute("id", name + "_" + optionId);
                    radio.MergeAttribute("name", name);
                    radio.MergeAttribute("type", "checkbox");
                    radio.MergeAttribute("value", item.Value);
                    radio.MergeAttribute("class", "checkbox");
                    //radio.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
                    if (ischecked) radio.MergeAttribute("checked", "checked");
                    if (htmlAttributes != null)
                    {
                        if (true.Equals(htmlAttributes["disabled"])
                            || "true".Equals(htmlAttributes["disabled"])
                            || "disabled".Equals(htmlAttributes["disabled"]))
                        {
                            radio.MergeAttribute("disabled", "disabled");
                        }
                    }

                    var label = new TagBuilder("label");
                    label.MergeAttribute("for", name + "_" + optionId);
                    label.SetInnerText(item.Text);

                    sb.Append(li.ToString(TagRenderMode.StartTag));
                    sb.Append(radio.ToString());
                    sb.Append(label.ToString());
                    sb.Append(li.ToString(TagRenderMode.EndTag));

                    optionId++;
                }
            }

            var hidden = new TagBuilder("input");
            hidden.MergeAttribute("id", name + "_val");
            hidden.MergeAttribute("name", name + "_val");
            hidden.MergeAttribute("type", "hidden");
            hidden.MergeAttribute("value", selectedValue);
            hidden.MergeAttributes(htmlAttributes, true);
            sb.Append(hidden.ToString());

            sb.Append(ul.ToString(TagRenderMode.EndTag));

            return sb;
        }

        #endregion

        #region RadioList

        public static MvcHtmlString RadioList(this HtmlHelper htmlHelper, string name, string selectedValue, string[] valueList, object htmlAttributes, string classname = "radio")
        {
            var list = valueList.Select(p => new SelectListItem
            {
                Value = p,
                Text = p,
                Selected = (p == selectedValue)
            });

            return RadioList(htmlHelper, name, list, htmlAttributes, classname);
        }

        public static MvcHtmlString RadioList(this HtmlHelper htmlHelper, string name, string selectedValue, IEnumerable<SelectListItem> selectList, object htmlAttributes, string classname = "radio")
        {
            var list = selectList.Select(p => new SelectListItem
            {
                Value = p.Value,
                Text = p.Text,
                Selected = p.Value == selectedValue
            });

            return RadioList(htmlHelper, name, list, htmlAttributes, classname);
        }

        public static MvcHtmlString RadioList(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, object htmlAttributes, string classname = "radio")
        {
            return RadioList(htmlHelper, name, selectList, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), classname);
        }

        public static MvcHtmlString RadioList(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, IDictionary<string, object> htmlAttributes, string classname = "radio")
        {
            return MvcHtmlString.Create(GetRadioHtmlBuilder(htmlHelper, name, selectList, htmlAttributes, classname).ToString());
        }
        private static StringBuilder GetRadioHtmlBuilder(HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, IDictionary<string, object> htmlAttributes, string classname)
        {
            var sb = new StringBuilder();

            var div = new TagBuilder("div");
            div.MergeAttribute("data-form", "radio");
            div.MergeAttribute("id", name);

            sb.Append(div.ToString(TagRenderMode.StartTag));

            string selectedValue = "";
            var optionId = 0;
            foreach (var item in selectList)
            {
                var ischecked = false;
                if (item.Selected)
                {
                    selectedValue = item.Value;
                    ischecked = true;
                }

                var label = new TagBuilder("label");
                label.AddCssClass(classname);
                //todo:disable,<label class="disabled">
                if (ischecked) label.AddCssClass("checked");

                var radio = new TagBuilder("input");
                radio.MergeAttribute("id", name + "_" + optionId);
                radio.MergeAttribute("name", name);
                radio.MergeAttribute("type", "radio");
                radio.MergeAttribute("value", item.Value);
                //radio.MergeAttribute("data-form", "radio");
                if (ischecked) radio.MergeAttribute("checked", "checked");
                if (htmlAttributes != null)
                {
                    if (true.Equals(htmlAttributes["disabled"])
                        || "true".Equals(htmlAttributes["disabled"])
                        || "disabled".Equals(htmlAttributes["disabled"]))
                    {
                        radio.MergeAttribute("disabled", "disabled");
                    }
                }

                sb.Append(label.ToString(TagRenderMode.StartTag));
                sb.Append(radio.ToString());
                sb.Append(item.Text);
                sb.Append(label.ToString(TagRenderMode.EndTag));
                //htmlHelper.Encode(" ") doesn't output &nbsp;
                //sb.Append(htmlHelper.Encode(" "));
                //sb.Append("&nbsp;&nbsp;");

                optionId++;
            }

            var hidden = new TagBuilder("input");
            hidden.MergeAttribute("id", name + "_val");
            hidden.MergeAttribute("name", name + "_val");
            hidden.MergeAttribute("type", "hidden");
            hidden.MergeAttribute("value", selectedValue);
            hidden.MergeAttributes(htmlAttributes, true);
            sb.Append(hidden.ToString());

            sb.Append(div.ToString(TagRenderMode.EndTag));

            return sb;
        }

        //private static StringBuilder GetRadioHtmlBuilder(HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, IDictionary<string, object> htmlAttributes, string classname)
        //{
        //    if (string.IsNullOrEmpty(classname)) classname = "radio";

        //    var div = new TagBuilder("div");
        //    div.MergeAttribute("data-form", "radio");
        //    div.MergeAttribute("id", name);

        //    var sb = new StringBuilder();
        //    sb.Append(div.ToString(TagRenderMode.StartTag));

        //    string selectedValue = "";
        //    var optionId = 0;
        //    foreach (var item in selectList)
        //    {
        //        var ischecked = false;
        //        if (item.Selected)
        //        {
        //            selectedValue = item.Value;
        //            ischecked = true;
        //        }

        //        var label = new TagBuilder("label");
        //        label.AddCssClass(classname);
        //        //label.MergeAttribute("data-rel", name);
        //        if (ischecked) label.AddCssClass("checked");

        //        var radio = new TagBuilder("input");
        //        radio.MergeAttribute("id", name + "_" + optionId);
        //        radio.MergeAttribute("name", name + "_items");
        //        radio.MergeAttribute("type", "radio");
        //        radio.MergeAttribute("value", item.Value);
        //        //radio.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        //        if (ischecked) radio.MergeAttribute("checked", "checked");

        //        sb.Append(label.ToString(TagRenderMode.StartTag));
        //        sb.Append(radio.ToString());
        //        sb.Append(item.Text);
        //        sb.Append(label.ToString(TagRenderMode.EndTag));

        //        optionId++;
        //    }

        //    var hidden = new TagBuilder("input");
        //    hidden.MergeAttribute("id", name + "_val");
        //    hidden.MergeAttribute("name", name + "_val");
        //    hidden.MergeAttribute("type", "hidden");
        //    hidden.MergeAttribute("value", selectedValue);
        //    hidden.MergeAttributes(htmlAttributes, true);
        //    sb.Append(hidden.ToString());

        //    sb.Append(div.ToString(TagRenderMode.EndTag));

        //    return sb;
        //}

        //private static StringBuilder GetRadioHtmlBuilder(HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, string data_fieldname, string fieldclass, string classname, string optionType)
        //{
        //    string format = string.Format("<li><input id=\"{{0}}\" type=\"{0}\" name=\"{{1}}\" value=\"{{2}}\" {{4}}/><label for=\"{{0}}\">{{3}}</label></li>", optionType);
        //    var sb = new StringBuilder();
        //    sb.Append(string.Format("<ul class=\"{0}\">", string.IsNullOrEmpty(classname) ? "radio" : classname));

        //    var optionId = 0;

        //    var selectedValue = "";
        //    var selectListItems = selectList as SelectListItem[] ?? selectList.ToArray();
        //    if (selectListItems.Any())
        //    {
        //        foreach (var item in selectListItems)
        //        {
        //            sb.Append(string.Format(format, new object[]  
        //            {  
        //                name + (string.IsNullOrEmpty(item.Value) ? optionId.ToString() : item.Value),  
        //                name,  
        //                item.Value,  
        //                item.Text,  
        //                item.Selected ? " checked=\"checked\"" : string.Empty
        //            }));
        //            optionId++;

        //            //当前选中的值
        //            if (item.Selected) selectedValue = item.Value;
        //        }
        //    }

        //    sb.Append(string.Format("<input type=\"hidden\" id=\"{0}\" name=\"{0}\" value=\"{1}\" class=\"{2}\" {3} />"
        //        , name + "_val"
        //        , selectedValue
        //        , fieldclass
        //        , string.IsNullOrEmpty(data_fieldname) ? string.Empty : string.Format(" data-fieldname=\"{0}\"", data_fieldname)));
        //    sb.Append("</ul>");

        //    return sb;
        //}

        #endregion

        #region CheckBoxList

        public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, string name, string selectedValue, string[] values, object htmlAttributes, string classname = "checkbox")
        {
            SelectList selectList = new SelectList(values);

            return CheckBoxList(htmlHelper, name, selectedValue, selectList, htmlAttributes, classname);
        }

        public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, string name, string selectedValue, IEnumerable<SelectListItem> selectList, object htmlAttributes, string classname = "checkbox")
        {
            var list = selectList.Select(p => new SelectListItem
            {
                Value = p.Value,
                Text = p.Text,
                Selected = p.Selected
            });

            if (!string.IsNullOrEmpty(selectedValue))
            {
                list = selectList.Select(p => new SelectListItem
                {
                    Value = p.Value,
                    Text = p.Text,
                    Selected = selectedValue.Split(',').Contains(p.Value) ? true : false
                });
            }

            return CheckBoxList(htmlHelper, name, list, htmlAttributes, classname);
        }

        public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, object htmlAttributes, string classname = "checkbox")
        {
            return CheckBoxList(htmlHelper, name, selectList, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), classname);
        }

        public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, IDictionary<string, object> htmlAttributes, string classname = "checkbox")
        {
            return MvcHtmlString.Create(GetCheckBoxHtmlBuilder(htmlHelper, name, selectList, htmlAttributes, classname).ToString());
        }

        private static StringBuilder GetCheckBoxHtmlBuilder(HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, IDictionary<string, object> htmlAttributes, string classname)
        {
            if (string.IsNullOrEmpty(classname)) classname = "checkbox";

            var div = new TagBuilder("div");
            div.MergeAttribute("data-form", "checkbox");
            div.MergeAttribute("id", name);

            var sb = new StringBuilder();
            sb.Append(div.ToString(TagRenderMode.StartTag));

            string selectedValue = "";
            var optionId = 0;
            var selectListItems = selectList as SelectListItem[] ?? selectList.ToArray();
            if (selectListItems.Any())
            {
                foreach (var item in selectListItems)
                {
                    var ischecked = false;
                    if (item.Selected)
                    {
                        selectedValue += item.Value + ",";
                        ischecked = true;
                    }

                    var label = new TagBuilder("label");
                    label.AddCssClass(classname);
                    //label.MergeAttribute("data-rel", name);
                    if (ischecked) label.AddCssClass("checked");

                    var checkbox = new TagBuilder("input");
                    checkbox.MergeAttribute("id", name + "_" + optionId);
                    checkbox.MergeAttribute("name", name);
                    checkbox.MergeAttribute("type", "checkbox");
                    checkbox.MergeAttribute("value", item.Value);
                    //radio.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
                    if (ischecked) checkbox.MergeAttribute("checked", "checked");
                    if (htmlAttributes != null)
                    {
                        if (true.Equals(htmlAttributes["disabled"])
                            || "true".Equals(htmlAttributes["disabled"])
                            || "disabled".Equals(htmlAttributes["disabled"]))
                        {
                            checkbox.MergeAttribute("disabled", "disabled");
                        }
                    }

                    sb.Append(label.ToString(TagRenderMode.StartTag));
                    sb.Append(checkbox.ToString());
                    sb.Append(item.Text);
                    sb.Append(label.ToString(TagRenderMode.EndTag));

                    optionId++;
                }
            }

            var hidden = new TagBuilder("input");
            hidden.MergeAttribute("id", name + "_val");
            hidden.MergeAttribute("name", name + "_val");
            hidden.MergeAttribute("type", "hidden");
            hidden.MergeAttribute("value", selectedValue.TrimEnd(','));
            hidden.MergeAttributes(htmlAttributes, true);
            sb.Append(hidden.ToString());

            sb.Append(div.ToString(TagRenderMode.EndTag));

            return sb;
        }

        #endregion

        #region DatePicker

        public static MvcHtmlString DatePicker(this HtmlHelper htmlHelper, string name, DateTime? value, string formatstr, object htmlAttributes)
        {
            return DatePicker(htmlHelper, name, value, formatstr, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString DatePicker(this HtmlHelper htmlHelper, string name, DateTime? value, string formatstr, IDictionary<string, object> htmlAttributes)
        {
            return MvcHtmlString.Create(GetDatePickerBuilder(htmlHelper, name, value, formatstr, htmlAttributes).ToString());
        }

        private static StringBuilder GetDatePickerBuilder(HtmlHelper htmlHelper, string name, DateTime? value, string formatstr, IDictionary<string, object> htmlAttributes)
        {
            if (string.IsNullOrEmpty(formatstr)) formatstr = "yyyy-MM-dd";

            var div = new TagBuilder("div");
            div.MergeAttribute("class", "input-group input-group-sm date datepicker");
            //div.MergeAttribute("data-date-autoclose", "true");a
            div.MergeAttribute("data-form", "datepicker");
            div.MergeAttribute("data-date", CommonStr.GetDateStr(value, formatstr));
            div.MergeAttribute("data-date-format", formatstr.Replace("MM", "mm"));

            var input = new TagBuilder("input");
            input.MergeAttribute("id", name);
            input.MergeAttribute("name", name);
            input.MergeAttribute("class", "form-control");
            input.MergeAttribute("value", CommonStr.GetDateStr(value, formatstr));
            input.MergeAttribute("type", "text");
            input.MergeAttributes(htmlAttributes, true);

            var sb = new StringBuilder();
            sb.Append(div.ToString(TagRenderMode.StartTag));
            sb.Append(input.ToString(TagRenderMode.Normal));
            sb.Append("<span class=\"input-group-addon\" style=\"width:auto;\"><i class=\"fa fa-calendar\"></i></span>");
            sb.Append(div.ToString(TagRenderMode.EndTag));

            return sb;
        }

        #endregion

        #region MonthPicker

        public static MvcHtmlString MonthPicker(this HtmlHelper htmlHelper, string name, DateTime? value, string formatstr, object htmlAttributes)
        {
            return MonthPicker(htmlHelper, name, value, formatstr, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString MonthPicker(this HtmlHelper htmlHelper, string name, DateTime? value, string formatstr, IDictionary<string, object> htmlAttributes)
        {
            return MvcHtmlString.Create(GetMonthPickerBuilder(htmlHelper, name, value, formatstr, htmlAttributes).ToString());
        }

        private static StringBuilder GetMonthPickerBuilder(HtmlHelper htmlHelper, string name, DateTime? value, string formatstr, IDictionary<string, object> htmlAttributes)
        {
            if (string.IsNullOrEmpty(formatstr)) formatstr = "yyyy-MM";

            var div = new TagBuilder("div");
            div.MergeAttribute("class", "input-group input-group-sm date datepicker");
            //div.MergeAttribute("data-date-autoclose", "true");
            div.MergeAttribute("data-form", "monthpicker");
            div.MergeAttribute("data-date", CommonStr.GetDateStr(value, formatstr));
            div.MergeAttribute("data-date-format", formatstr.Replace("MM", "mm"));

            var input = new TagBuilder("input");
            input.MergeAttribute("id", name);
            input.MergeAttribute("name", name);
            input.MergeAttribute("class", "form-control");
            input.MergeAttribute("value", CommonStr.GetDateStr(value, formatstr));
            input.MergeAttribute("type", "text");
            input.MergeAttributes(htmlAttributes, true);

            var sb = new StringBuilder();
            sb.Append(div.ToString(TagRenderMode.StartTag));
            sb.Append(input.ToString(TagRenderMode.Normal));
            sb.Append("<span class=\"input-group-addon\" style=\"width:auto;\"><i class=\"fa fa-calendar\"></i></span>");
            sb.Append(div.ToString(TagRenderMode.EndTag));

            return sb;
        }

        #endregion

        #region YearPicker

        public static MvcHtmlString YearPicker(this HtmlHelper htmlHelper, string name, DateTime? value, string formatstr, object htmlAttributes)
        {
            return YearPicker(htmlHelper, name, value, formatstr, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString YearPicker(this HtmlHelper htmlHelper, string name, DateTime? value, string formatstr, IDictionary<string, object> htmlAttributes)
        {
            return MvcHtmlString.Create(GetYearPickerBuilder(htmlHelper, name, value, formatstr, htmlAttributes).ToString());
        }

        private static StringBuilder GetYearPickerBuilder(HtmlHelper htmlHelper, string name, DateTime? value, string formatstr, IDictionary<string, object> htmlAttributes)
        {
            if (string.IsNullOrEmpty(formatstr)) formatstr = "yyyy";

            var div = new TagBuilder("div");
            div.MergeAttribute("class", "input-group input-group-sm date datepicker");
            //div.MergeAttribute("data-date-autoclose", "true");
            div.MergeAttribute("data-form", "yearpicker");
            div.MergeAttribute("data-date", CommonStr.GetDateStr(value, formatstr));
            div.MergeAttribute("data-date-format", formatstr.Replace("MM", "mm"));

            var input = new TagBuilder("input");
            input.MergeAttribute("id", name);
            input.MergeAttribute("name", name);
            input.MergeAttribute("class", "form-control");
            input.MergeAttribute("value", CommonStr.GetDateStr(value, formatstr));
            input.MergeAttribute("type", "text");
            input.MergeAttributes(htmlAttributes, true);

            var sb = new StringBuilder();
            sb.Append(div.ToString(TagRenderMode.StartTag));
            sb.Append(input.ToString(TagRenderMode.Normal));
            sb.Append("<span class=\"input-group-addon\" style=\"width:auto;\"><i class=\"fa fa-calendar\"></i></span>");
            sb.Append(div.ToString(TagRenderMode.EndTag));

            return sb;
        }

        #endregion

        #region ColorPicker

        /// <summary>
        /// 
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <param name="htmlAttributes"></param>
        /// <returns></returns>
        public static MvcHtmlString ColorPicker(this HtmlHelper htmlHelper, string name, string value, object htmlAttributes)
        {
            return MvcHtmlString.Create(GetColorPickerBuilder(htmlHelper, name, value, "hex", htmlAttributes).ToString());
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <param name="colorformat">hex/rgba</param>
        /// <param name="htmlAttributes"></param>
        /// <returns></returns>
        public static MvcHtmlString ColorPicker(this HtmlHelper htmlHelper, string name, string value, string colorformat, object htmlAttributes)
        {
            return MvcHtmlString.Create(GetColorPickerBuilder(htmlHelper, name, value, colorformat, htmlAttributes).ToString());
        }

        private static StringBuilder GetColorPickerBuilder(HtmlHelper htmlHelper, string name, string value, string colorformat, object htmlAttributes)
        {
            //IDictionary<string, object> attrlist = (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

            if (string.IsNullOrEmpty(colorformat)) colorformat = "hex";

            var div = new TagBuilder("div");
            div.MergeAttribute("class", "input-append color");
            div.MergeAttribute("data-id", name);
            div.MergeAttribute("data-form", "colorpicker");
            div.MergeAttribute("data-color", value);
            div.MergeAttribute("data-color-format", colorformat);

            var input = new TagBuilder("input");
            input.MergeAttribute("id", name);
            input.MergeAttribute("name", name);
            input.MergeAttribute("style", "width:180px;");
            input.MergeAttribute("value", value);
            input.MergeAttribute("type", "text");
            input.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), true);

            var sb = new StringBuilder();
            sb.Append(div.ToString(TagRenderMode.StartTag));
            sb.Append(input.ToString(TagRenderMode.Normal));
            sb.Append("<span class=\"add-on\"><i style=\"background-color:" + value + ";\"></i></span>");
            sb.Append(div.ToString(TagRenderMode.EndTag));

            return sb;
        }

        #endregion

        #region WYUploadFile

        /// <summary>
        /// 控件名称
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="name">控件名称</param>
        /// <param name="fileurl">已上传的文件url</param>
        /// <param name="buttontext">上传按钮显示名称</param>
        /// <param name="path">目录名称</param>
        /// <param name="maxfilesize">文件最大限制（Byte，0表示默认限制5M）</param>
        /// <param name="allowextension">允许的文件类型（*表示不限制，多个用逗号隔开）</param>
        /// <param name="htmlAttributes"></param>
        /// <returns></returns>
        public static MvcHtmlString WYUploadFile(this HtmlHelper htmlHelper, string name, string fileurl, string filename, string buttontext, string path, int maxfilesize, string allowextension, object htmlAttributes)
        {
            var div = new TagBuilder("div");
            div.MergeAttribute("id", name);
            div.MergeAttribute("data-form", "wyupload");
            div.MergeAttribute("data-path", path);
            div.MergeAttribute("data-maxfilesize", maxfilesize == 0 ? "5242880" : maxfilesize.ToString("#"));
            div.MergeAttribute("data-allowex", allowextension);
            div.MergeAttribute("data-fileurl", fileurl);
            div.MergeAttribute("data-filename", filename);

            var divbtn = new TagBuilder("div");
            divbtn.AddCssClass("btn btn-mini btn-default fileinput-button");

            var btntext = new TagBuilder("span");
            btntext.InnerHtml = buttontext;

            var input = new TagBuilder("input");
            input.MergeAttribute("id", "file_" + name);
            input.MergeAttribute("name", "file_" + name);
            input.MergeAttribute("type", "file");

            var labelprogress = new TagBuilder("label");
            labelprogress.AddCssClass("upload-progress");
            labelprogress.MergeAttribute("style", "margin-left:5px;");

            var labelfilename = new TagBuilder("label");
            labelfilename.AddCssClass("upload-filename");
            labelfilename.MergeAttribute("style", "margin-left:5px;");
            labelfilename.InnerHtml = filename;

            var inputfileurl = new TagBuilder("input");
            inputfileurl.MergeAttribute("id", name);
            inputfileurl.MergeAttribute("name", name);
            inputfileurl.MergeAttribute("type", "hidden");
            inputfileurl.MergeAttribute("value", fileurl);
            inputfileurl.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), true);

            var sb = new StringBuilder();
            sb.Append(div.ToString(TagRenderMode.StartTag));

            sb.Append(divbtn.ToString(TagRenderMode.StartTag));
            sb.Append(btntext.ToString());
            sb.Append(input.ToString());
            sb.Append(divbtn.ToString(TagRenderMode.EndTag));

            sb.Append(labelprogress.ToString());
            sb.Append(labelfilename.ToString());
            sb.Append(inputfileurl.ToString());

            sb.Append(div.ToString(TagRenderMode.EndTag));

            return MvcHtmlString.Create(sb.ToString());
        }

        #endregion

        #region WYCombo

        public static MvcHtmlString WYCombo(this HtmlHelper htmlHelper, string name, string valuefield, IEnumerable<SelectListItem> selectList, object htmlAttributes)
        {
            var selected = selectList.Where(p => p.Selected == true).FirstOrDefault();

            return WYCombo(htmlHelper, name, selected == null ? "" : selected.Value, selected == null ? "" : selected.Text, valuefield, selectList, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString WYCombo(this HtmlHelper htmlHelper, string name, string selectedValue, string selectedText, string valuefield, IEnumerable<SelectListItem> selectList, object htmlAttributes)
        {
            SelectListItem selected = null;
            if (!string.IsNullOrEmpty(selectedValue))
            {
                selected = selectList.Where(p => selectedValue.Equals(p.Value, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
            }
            if (selected == null && !string.IsNullOrEmpty(selectedText))
            {
                selected = selectList.Where(p => selectedText.Equals(p.Text, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
            }

            selectedValue = selected == null ? selectedValue : selected.Value;
            selectedText = selected == null ? selectedText : selected.Text;

            return WYCombo(htmlHelper, name, selectedValue, selectedText, valuefield, selectList, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString WYCombo(this HtmlHelper htmlHelper, string name, string selectedValue, string selectedText, string valuefield, IEnumerable<SelectListItem> selectList, IDictionary<string, object> htmlAttributes)
        {
            var sb = new StringBuilder();

            var datas = new List<object>();

            foreach (var item in selectList)
            {
                var option = new
                {
                    value = item.Value,
                    text = item.Text
                };

                datas.Add(option);
            }

            var input = new TagBuilder("input");
            input.MergeAttribute("id", name);
            input.MergeAttribute("name", name);
            input.MergeAttribute("type", "text");
            input.MergeAttribute("data-form", "wycombo");
            input.MergeAttribute("data-value", selectedValue);
            input.MergeAttribute("data-datas", System.Web.Helpers.Json.Encode(datas));

            input.MergeAttributes(htmlAttributes);
            input.Attributes.Remove("data-fieldname");

            input.MergeAttribute("value", selectedText);
            input.AddCssClass("input-sm");

            var dropbtn = new TagBuilder("i");
            dropbtn.AddCssClass("fa fa-chevron-down");
            dropbtn.AddCssClass("dropdown-btn");

            var container = new TagBuilder("div");
            container.AddCssClass("input-icon on-right icon-sm");
            if (htmlAttributes.ContainsKey("style"))
            {
                container.MergeAttribute("style", htmlAttributes["style"].ToString(), true);
            }
            container.MergeAttribute("style", "position:relative;");

            sb.Append(container.ToString(TagRenderMode.StartTag));

            sb.Append(input.ToString());
            sb.Append(dropbtn.ToString());

            var hidden = new TagBuilder("input");
            hidden.MergeAttribute("id", name + "_val");
            hidden.MergeAttribute("name", name + "_val");
            hidden.MergeAttribute("type", "hidden");
            hidden.MergeAttribute("value", selectedValue);
            hidden.MergeAttributes(htmlAttributes, true);
            sb.Append(hidden.ToString());

            sb.Append(container.ToString(TagRenderMode.EndTag));

            return MvcHtmlString.Create(sb.ToString());
        }

        public static MvcHtmlString WYComboAjax(this HtmlHelper htmlHelper, string name, string valuefield, string url, string cols, object htmlAttributes)
        {
            return WYComboAjax(htmlHelper, name, "", "", valuefield, url, cols, new Dictionary<string, string>(), (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString WYComboAjax(this HtmlHelper htmlHelper, string name, string selectedValue, string selectedText, string valuefield, string url, string cols, object htmlAttributes)
        {
            return WYComboAjax(htmlHelper, name, selectedValue, selectedText, valuefield, url, cols, new Dictionary<string, string>(), (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString WYComboAjax(this HtmlHelper htmlHelper, string name, string valuefield, string url, string cols, IDictionary<string, string> paramslist, object htmlAttributes)
        {
            return WYComboAjax(htmlHelper, name, "", "", valuefield, url, cols, paramslist, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString WYComboAjax(this HtmlHelper htmlHelper, string name, string selectedValue, string selectedText, string valuefield, string url, string cols, IDictionary<string, string> paramslist, object htmlAttributes)
        {
            return WYComboAjax(htmlHelper, name, selectedValue, selectedText, valuefield, url, cols, paramslist, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString WYComboAjax(this HtmlHelper htmlHelper, string name, string selectedValue, string selectedText, string valuefield, string url, string cols, IDictionary<string, string> paramslist, IDictionary<string, object> htmlAttributes)
        {
            var sb = new StringBuilder();

            var input = new TagBuilder("input");
            input.MergeAttribute("id", name);
            input.MergeAttribute("name", name);
            input.MergeAttribute("type", "text");
            input.MergeAttribute("data-form", "wycombo");
            input.MergeAttribute("data-value", selectedValue);
            input.MergeAttribute("data-url", url);
            if (!string.IsNullOrEmpty(cols))
            {
                input.MergeAttribute("data-cols", cols);
            }
            if (paramslist != null && paramslist.Count > 0)
            {
                input.MergeAttribute("data-params", System.Web.Helpers.Json.Encode(paramslist));
            }
            input.MergeAttribute("data-textfield", valuefield);

            input.MergeAttributes(htmlAttributes);
            input.Attributes.Remove("data-fieldname");

            input.MergeAttribute("value", selectedText);
            input.AddCssClass("input-sm");

            var dropbtn = new TagBuilder("i");
            dropbtn.AddCssClass("fa fa-chevron-down");
            dropbtn.AddCssClass("dropdown-btn");

            var container = new TagBuilder("div");
            container.AddCssClass("input-icon on-right icon-sm");
            if (htmlAttributes.ContainsKey("style"))
            {
                container.MergeAttribute("style", htmlAttributes["style"].ToString(), true);
            }

            sb.Append(container.ToString(TagRenderMode.StartTag));
            sb.Append(input.ToString());
            sb.Append(dropbtn.ToString());

            var hidden = new TagBuilder("input");
            hidden.MergeAttribute("id", name + "_val");
            hidden.MergeAttribute("name", name + "_val");
            hidden.MergeAttribute("type", "hidden");
            hidden.MergeAttribute("value", selectedValue);
            hidden.MergeAttributes(htmlAttributes, true);
            sb.Append(hidden.ToString());

            sb.Append(container.ToString(TagRenderMode.EndTag));

            return MvcHtmlString.Create(sb.ToString());
        }


        #region 新扩展WYComboAjax方法
        public static MvcHtmlString WYComboAjax(this HtmlHelper htmlHelper, string name, string valuefield, string url, string cols, object htmlAttributes, object onSelected)
        {
            return WYComboAjax(htmlHelper, name, valuefield, url, cols, new Dictionary<string, string>(), (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), onSelected);
        }
        public static MvcHtmlString WYComboAjax(this HtmlHelper htmlHelper, string name, string valuefield, string url, string cols, IDictionary<string, string> paramslist, object htmlAttributes, object onSelected)
        {
            return WYComboAjax(htmlHelper, name, valuefield, url, cols, paramslist, (IDictionary<string, object>)HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), onSelected);
        }
        public static MvcHtmlString WYComboAjax(this HtmlHelper htmlHelper, string name, string valuefield, string url, string cols, IDictionary<string, string> paramslist, IDictionary<string, object> htmlAttributes, object onSelected)
        {
            var sb = new StringBuilder();

            var selectedValue = "";
            var selectedText = "";

            var input = new TagBuilder("input");
            input.MergeAttribute("id", name);
            input.MergeAttribute("name", name);
            input.MergeAttribute("type", "text");
            input.MergeAttribute("data-form", "wycombo");
            input.MergeAttribute("data-value", selectedValue);
            input.MergeAttribute("data-url", url);
            if (!string.IsNullOrEmpty(cols))
            {
                input.MergeAttribute("data-cols", cols);
            }


            if (paramslist != null && paramslist.Count > 0)
            {
                input.MergeAttribute("data-params", System.Web.Helpers.Json.Encode(paramslist));
            }
            if (Utils.NvStr(onSelected) != "")
            {
                input.MergeAttribute("data-onselected", Utils.NvStr(onSelected));
            }

            input.MergeAttribute("data-textfield", valuefield);

            input.MergeAttributes(htmlAttributes);
            input.Attributes.Remove("data-fieldname");

            input.MergeAttribute("value", selectedText);
            input.AddCssClass("input-sm");

            var dropbtn = new TagBuilder("i");
            dropbtn.AddCssClass("fa fa-chevron-down");
            dropbtn.AddCssClass("dropdown-btn");

            var container = new TagBuilder("div");
            container.AddCssClass("input-icon on-right icon-sm");
            container.MergeAttribute("style", "position:relative;");
            if (htmlAttributes.ContainsKey("style"))
            {
                container.MergeAttribute("style", htmlAttributes["style"].ToString(), true);
            }

            sb.Append(container.ToString(TagRenderMode.StartTag));
            sb.Append(input.ToString());
            sb.Append(dropbtn.ToString());

            var hidden = new TagBuilder("input");
            hidden.MergeAttribute("id", name + "_val");
            hidden.MergeAttribute("name", name + "_val");
            hidden.MergeAttribute("type", "hidden");
            hidden.MergeAttribute("value", selectedValue);
            hidden.MergeAttributes(htmlAttributes, true);
            sb.Append(hidden.ToString());

            sb.Append(container.ToString(TagRenderMode.EndTag));

            return MvcHtmlString.Create(sb.ToString());
        }
        #endregion
        #endregion

    }

}